<template>
  <div class="user-profile">
    <div
      class="avatar-container"
      @mouseover="showOverlay = true"
      @mouseout="showOverlay = false"
      @click="showDialog = true"
    >
      <img :src="avatarUrl" class="preview-image" />
      <div v-if="showOverlay" class="overlay">
        <span>更换头像</span>
      </div>
    </div>
  </div>
  <el-dialog v-model="showDialog" title="更换头像">
    <el-row>
      <el-col :xs="24" :md="12">
        <vueCropper
          class="image-container"
          ref="cropper"
          :img="option.img"
          :outputSize="option.outputSize"
          :outputType="option.outputType"
          :info="option.info"
          :canScale="option.canScale"
          :autoCrop="option.autoCrop"
          :autoCropWidth="option.autoCropWidth"
          :autoCropHeight="option.autoCropHeight"
          :fixedBox="option.fixedBox"
          :fixed="option.fixed"
          :fixedNumber="option.fixedNumber"
          :canMove="option.canMove"
          :canMoveBox="option.canMoveBox"
          :original="option.original"
          :centerBox="option.centerBox"
          :infoTrue="option.infoTrue"
          :full="option.full"
          :enlarge="option.enlarge"
          :mode="option.mode"
          @realTime="handleRealtime"
        >
        </vueCropper>
      </el-col>
      <el-col :xs="24" :md="12">
        <div class="preview-container">
          <img :src="imgUrl" class="preview-image" />
        </div>
      </el-col>
    </el-row>
    <el-row style="width: 100%; height: 60px; margin-top: 10px">
      <el-upload
        :auto-upload="false"
        :show-file-list="false"
        :on-change="handleChange"
      >
        <el-button type="primary">
          <el-icon><FolderOpened /></el-icon>
        </el-button>
      </el-upload>
      <el-button
        :disabled="!option.img"
        style="margin-left: 15px"
        type="primary"
        @click="rotateLeft"
      >
        <el-icon><RefreshLeft /></el-icon>
      </el-button>
      <el-button :disabled="!option.img" type="primary" @click="rotateRight">
        <el-icon><RefreshRight /></el-icon>
      </el-button>
      <el-button :disabled="!option.img" type="primary" @click="addSize">
        <el-icon><Plus /></el-icon>
      </el-button>
      <el-button :disabled="!option.img" type="primary" @click="reduceSize">
        <el-icon><Minus /></el-icon>
      </el-button>
    </el-row>
    <template #footer>
      <el-button @click="showDialog = false">取消</el-button>
      <el-button type="primary" :disabled="!option.img" @click="imageUpload">
        上传
      </el-button>
    </template>
  </el-dialog>
</template>
<script lang="ts">
export default {
  name: "Avatar",
};
</script>
<script setup lang="ts">
import { uploadAvatarApi } from "@/api/file";
import type { UploadProps, UploadFile } from "element-plus";
import { useUserStore } from "@/store/modules/user";

const { avatarUrl } = defineProps(["avatarUrl"]);
const userStore = useUserStore();
const emit = defineEmits(["updateAvatar"]);

const cropper = ref();
let option = reactive({
  img: "", // 裁剪图片的地址 url 地址, base64, blob
  outputSize: 1, // 裁剪生成图片的质量
  outputType: "jpeg", // 裁剪生成图片的格式 jpeg, png, webp
  info: true, // 裁剪框的大小信息
  canScale: true, // 图片是否允许滚轮缩放
  autoCrop: true, // 是否默认生成截图框
  autoCropWidth: 150, // 默认生成截图框宽度
  autoCropHeight: 150, // 默认生成截图框高度
  fixedBox: false, // 固定截图框大小 不允许改变
  fixed: false, // 是否开启截图框宽高固定比例，这个如果设置为true，截图框会是固定比例缩放的，如果设置为false，则截图框的狂宽高比例就不固定了
  fixedNumber: [1, 1], // 截图框的宽高比例 [ 宽度 , 高度 ]
  canMove: true, // 上传图片是否可以移动
  canMoveBox: true, // 截图框能否拖动
  original: false, // 上传图片按照原始比例渲染
  centerBox: true, // 截图框是否被限制在图片里面
  infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  full: true, // 是否输出原图比例的截图
  enlarge: "1", // 图片根据截图框输出比例倍数
  mode: "contain", // 图片默认渲染方式 contain , cover, 100px, 100% auto
});

const showOverlay = ref(false);
const showDialog = ref(false);
const imgUrl = ref("");
const fileName = ref("");

// 向左旋转图片
const rotateLeft = () => {
  cropper.value.rotateLeft();
};

// 向右旋转
const rotateRight = () => {
  cropper.value.rotateRight();
};

// 放大图片
const addSize = () => {
  cropper.value.changeScale(1);
};

// 缩小图片
const reduceSize = () => {
  cropper.value.changeScale(-1);
};

// 实时预览
const handleRealtime = () => {
  cropper.value.getCropData((data: any) => {
    imgUrl.value = data;
  });
};

const fileList = ref([]);
// el-upload的change事件，具体看element-plus的官网
const handleChange: UploadProps["onChange"] = (uploadFile: UploadFile) => {
  const isFileType =
    uploadFile.raw?.type === "image/jpeg" ||
    uploadFile.raw?.type === "image/png";
  // 约束上传文件类型
  if (!isFileType) {
    ElMessage.error("只允许上传JPG和PNG格式的图片");
    return;
  }
  option.img = URL.createObjectURL(uploadFile.raw!);
  fileName.value = uploadFile.name;
};

const imageUpload = async () => {
  try {
    const blob = await fetch(imgUrl.value).then((r) => r.blob());
    const { data } = await uploadAvatarApi(blob, fileName.value);
    ElMessage.success("头像上传成功");
    showDialog.value = false;
    emit("updateAvatar", data.url);
  } catch (error) {
    ElMessage.error("头像上传失败");
  }
};

// 当 dialog 关闭的时候清空图片
watch(
  () => showDialog.value,
  (newVal) => {
    if (!newVal) {
      fileList.value = [];
      option.img = "";
      imgUrl.value = "";
    } else {
      // 画面初始化的时候显示原本的头像
      if (userStore.user.avatar) {
        imgUrl.value = userStore.user.avatar;
      }
    }
  }
);
</script>

<style scoped>
.user-profile {
  display: flex;
  align-items: center;
  gap: 10px;
}

.avatar-container {
  position: relative;
  width: 100px;
  height: 100px;
  overflow: hidden;
  border-radius: 50%;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  opacity: 0;
  transition: opacity 0.9s;
  pointer-events: none;
}

.avatar-container:hover .overlay {
  opacity: 1;
}

.image-container {
  width: 250px !important;
  height: 250px !important;
}

.preview-container {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  overflow: hidden;
  position: relative;
}

.preview-image {
  position: absolute;
  width: 100%;
  height: 100%;
  margin: auto;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  object-fit: cover;
}
</style>
